package com.teamblueplus.comicmaker;

import java.util.ArrayList;

import com.teamblueplus.R;
import com.teamblueplus.brush.PaintBrush;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.SurfaceHolder;

/**
 * This class is the drawing thread of ComicMaking, thread is running in a loop
 * for drawing
 * 
 * @author qui
 * 
 */
class ComicDrawThread extends Thread {
	String TAG = "DrawingThread";
	private SurfaceHolder _surfaceHolder;
	private boolean _run = false;
	public volatile boolean isDrawing = true;
	Bitmap bubbleBitmap;
	Bitmap background;
	Bitmap tempBitmap;
	boolean drawImageBackground = false;
	ArrayList<DrawingLayer> layerArray;

	boolean touched; // check for touch input
	boolean isSaved = false;
	boolean isSelected;
	private int selectedLayer;

	private Resources mRes;
	private Context mContext; // context of activity

	Paint rectPaint; // for highlight selected layer

	int selectedLayerX; // for moving layer
	int selectedLayerY; // for moving layer

	boolean sleep;

	// ########################################################
	// for brush functionality
	public PaintBrush brush2;
	public Bitmap mBitmap;
	
	//flag to know whethere to draw highlight on image or not
	private boolean drawHighlight = true;

	// use for brush functionality
	// not useful for now
	private Handler previewDoneHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			Log.d("draw", "handleMessage is Drawing FALSE");
			// isDrawing = false;
		}
	};

	// ########################################################

	/**
	 * constructor for the drawing thread
	 * 
	 * @param surfaceHolder
	 * @param context
	 */
	public ComicDrawThread(SurfaceHolder surfaceHolder, Context context,
			ArrayList<DrawingLayer> array) {
		_surfaceHolder = surfaceHolder;
		mContext = context;
		mRes = context.getResources();

		layerArray = array;

		// create bubble and load bitmap
		bubbleBitmap = BitmapFactory.decodeResource(mRes,
				R.drawable.bubble_image);

		rectPaint = new Paint();
		rectPaint.setColor(Color.GREEN);
		rectPaint.setStrokeWidth(4);
		rectPaint.setStyle(Paint.Style.STROKE);

		// brush functionality
		// init brush
		brush2 = new PaintBrush();
		mBitmap = null;

		sleep = true;

	}

	public void setRunning(boolean run) {
		_run = run;
	}

	@Override
	public void run() {
		Canvas c;
		while (_run) {
			if (isDrawing) {
				c = null;
				try {
					if (_surfaceHolder == null) {
						Log.d("Surface Holder", "is null");
					}

					c = _surfaceHolder.lockCanvas();
					synchronized (_surfaceHolder) {
						draw(c);
					}
				} finally {
					// do this in a finally so that if an exception is thrown
					// during the above, we don't leave the Surface in an
					// inconsistent state
					if (c != null) {
						_surfaceHolder.unlockCanvasAndPost(c);
					}
				}
			}
		}
	}

	/**
	 * Main draw method
	 * 
	 * @param canvas
	 */
	public void draw(Canvas canvas) {
		// for changing of activity, pause, resume
		if (canvas == null) {
			return;
		}
		
		// canvas.drawColor(Color.rgb(187, 255, 255));

		// #################################################################
		// drawing the brush

		// if(mBitmap == null){
		// Log.d("###", "initialize mBitmap");
		// mBitmap = Bitmap.createBitmap (1, 1, Bitmap.Config.ARGB_8888);
		// }

		// #################################################################
		// drawing the brush

		if (mBitmap == null) {
			Log.d(TAG, "initialize mBitmap");
			mBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
		}

		// we created another canvas with bitmap as parameter so the canvas
		// will be draw into the bitmap, the bitmap will be use to save all
		// the drawings when we save it to a file.
		final Canvas c2 = new Canvas(mBitmap);

		// draw black background
		if (this.drawImageBackground)
			c2.drawBitmap(this.background, 0, 0, null);
		else
			c2.drawColor(Color.WHITE);

		// draw image layer
		for (int i = 0; i < layerArray.size(); i++) {
			DrawingLayer layer = layerArray.get(i);
			Bitmap layerBitmap = layer.getBitmap();
			int layerWidth = layer.getBitmap().getWidth();
			int layerHeight = layer.getBitmap().getHeight();
			c2.drawBitmap(layerBitmap, layer.getxLoc() - (layerWidth / 2),
					layer.getyLoc() - (layerHeight / 2), null);

			// draw highlight for selected image
			 if (i == selectedLayer && drawHighlight) {
				 float left = layer.getxLoc() - (layerWidth / 2) - 1;
				 float top = layer.getyLoc() - (layerHeight / 2) - 1;
				 float right = left + layerWidth + 1;
				 float bottom = top + layerHeight + 1;
				 c2.drawRect(left, top, right, bottom, rectPaint);
			 }
		}

		// draw all the save path of brush
		brush2.executeAll(c2, previewDoneHandler);

		// draw the preview path
		c2.drawPath(brush2.currentDrawingPath.path,
				brush2.currentDrawingPath.paint);

		// #################################################################

		// this canvas just display the bitmaps on the screen
		canvas.drawBitmap(mBitmap, 0, 0, null);

	}
	
	public void onDrawFinal(Canvas canvas) {
		// for changing of activity, pause, resume
		if (canvas == null) {
			return;
		}
	
		if (mBitmap == null) {
			Log.d(TAG, "initialize mBitmap");
			mBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
		}

		// we created another canvas with bitmap as parameter so the canvas
		// will be draw into the bitmap, the bitmap will be use to save all
		// the drawings when we save it to a file.
		final Canvas c2 = new Canvas(mBitmap);

		// draw black background
		if (this.drawImageBackground)
			c2.drawBitmap(this.background, 0, 0, null);
		else
			c2.drawColor(Color.WHITE);

		// draw image layer
		for (int i = 0; i < layerArray.size(); i++) {
			DrawingLayer layer = layerArray.get(i);
			Bitmap layerBitmap = layer.getBitmap();
			int layerWidth = layer.getBitmap().getWidth();
			int layerHeight = layer.getBitmap().getHeight();
			c2.drawBitmap(layerBitmap, layer.getxLoc() - (layerWidth / 2),
					layer.getyLoc() - (layerHeight / 2), null);

		}
		
		tempBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.createdbycomicmaker);
		
		c2.drawBitmap(tempBitmap, 0, c2.getHeight()-55, null);

		// draw all the save path of brush
		brush2.executeAll(c2, previewDoneHandler);

		// draw the preview path
		c2.drawPath(brush2.currentDrawingPath.path,
				brush2.currentDrawingPath.paint);
		
	

		// #################################################################

		// this canvas just display the bitmaps on the screen
		canvas.drawBitmap(mBitmap, 0, 0, null);

	}

	/**
	 * when user touches the screen, layer is selected if touched
	 * 
	 * @param eventX
	 * @param eventY
	 */
	public void handleActionDown(int eventX, int eventY) {
		// get selected layer by touching
		for (int i = layerArray.size() - 1; i >= 0; i--) {
			DrawingLayer layer = layerArray.get(i);
			int layerWidth = layer.getBitmap().getWidth();
			int layerHeight = layer.getBitmap().getHeight();

			if (eventX >= (layer.getxLoc() - layerWidth / 2)
					&& (eventX <= (layer.getxLoc() + layerWidth / 2))) {
				if (eventY >= (layer.getyLoc() - layerHeight / 2)
						&& (eventY <= (layer.getyLoc() + layerHeight / 2))) {

					selectedLayerX = layer.getxLoc();
					selectedLayerY = layer.getyLoc();
					Log.d("Drawing thread", "touched layer is " + i);
					setSelectedLayer(i);
					setTouched(true);
					break;
				} else {
					setTouched(false);
				}
			} else {
				setTouched(false);
			}
		}

	}

	/*
	 * Call resize
	 */
	public void resizeLayer(float initialDistance, float currentDistance) {
		layerArray.get(selectedLayer).resize(initialDistance, currentDistance);
	}

	public void setNewLayerSize() {
		layerArray.get(selectedLayer).setNewSize();
	}

	// ------------- getters and setters -----------------------

	/*
	 * Set screen touch to true
	 */
	public void setTouched(boolean touched) {
		this.touched = touched;
	}

	/*
	 * Check if the user touches the screen
	 */
	public boolean isTouched() {
		return touched;
	}

	public void setSelectedLayer(int layer) {
		this.selectedLayer = layer;
		isSelected = true;
	}

	public int getSelectedLayer() {
		return selectedLayer;
	}

	public int getSelectedLayerXLoc() {
		return selectedLayerX;
	}

	public int getSelectedLayerYLoc() {
		return selectedLayerY;
	}

	// set image array after thread being resume
	public void setLayerArray(ArrayList<DrawingLayer> layerArray) {
		this.layerArray = layerArray;
	}

	/*
	 * getter of image array for data saving
	 */
	public ArrayList<DrawingLayer> getLayerArray() {
		return this.layerArray;
	}

	// set isSaved to save image
	public void setSave(boolean value) {
		isSaved = value;
	}

	/*
	 * set the type of brush
	 */
	public void setBrushArray(PaintBrush brush) {
		this.brush2 = brush;

	}

	/*
	 * get Bitmap for saving the image
	 */
	public Bitmap getBitmap() {
		this.isDrawing = false;
		this.drawHighlight = false;
		
		Canvas c;
		c = null;
		try {
			if (_surfaceHolder == null) {
				Log.d("Surface Holder", "is null");
			}

			c = _surfaceHolder.lockCanvas();
			synchronized (_surfaceHolder) {
				onDrawFinal(c);
			}
		} finally {
			// do this in a finally so that if an exception is thrown
			// during the above, we don't leave the Surface in an
			// inconsistent state
			if (c != null) {
				_surfaceHolder.unlockCanvasAndPost(c);
			}
		}
		
		
		return this.mBitmap;
	}
	
	/*
	 * clean up Bitmap
	 */
	public void cleanup() {
		bubbleBitmap.recycle();
		if (background != null) {
			background.recycle();
		}
		if (tempBitmap != null) {
			tempBitmap.recycle();
		}
		if (mBitmap != null){
			mBitmap.recycle();
		}
	}

}